package main

import (
	"encoding/json"
	"fmt"
	"strconv"
)

//slice 作为函数参数时，最好传递地址，否则可能不一致

func ChangeSlice(ss []string) {
	for i := 0; i < 111; i++ {
		ss = append(ss, strconv.Itoa(i))
	}
}

func ChangeSlicePtr(ss *[]string) *[]string {
	for i := 0; i < 111; i++ {
		*ss = append(*ss, strconv.Itoa(i))
	}
	return ss
}

func main() {
	var ss []string
	ChangeSlice(ss) //[]
	fmt.Println(ss)
	fmt.Println("-----------")

	var ss2 []string
	ChangeSlice(ss2)
	fmt.Println(len(ss2), cap(ss2))
	fmt.Println(len(ss), cap(ss))

	ssp := &ss
	ptr := ChangeSlicePtr(ssp)
	ChangeSlicePtr(&ss2)
	fmt.Println(len(ss2), cap(ss2))
	fmt.Println(len(ss), cap(ss))
	//fmt.Println(ssp) //&[0 1 2 3 4 5 6 7 8 9]

	//fmt.Println(ptr) //&[0 1 2 3 4 5 6 7 8 9]

	fmt.Println(ssp == &ss) //true 为啥呢？因为数组后面的空间没被占用？？
	fmt.Println(ptr == &ss) //true

	{
		//空切片和零值切片确实是在日常的工作中比较容易混淆的，且后期排查过程中也会比较麻烦。
		// 二者通过 fmt.Println 打印输出的结果都是 []，而且它们的 length 值和 capacity 值都是一样的，因此就会认为这二者是一个东西。
		// 最重要的是，json序列化的结果是不一样的！！！
		fmt.Println("-----------")
		var ss3 []string
		fmt.Println(ss3 == nil)         //wtf true!!!
		fmt.Println(len(ss3), cap(ss3)) //0 0

		ss4 := make([]string, 0)        //所以推荐这种
		fmt.Println(ss4 == nil)         //false
		fmt.Println(len(ss4), cap(ss4)) //0 0

		ss3s, _ := json.Marshal(ss3)
		ss4s, _ := json.Marshal(ss4)
		fmt.Println("ss3s:", string(ss3s)) //null
		fmt.Println("ss4s:", string(ss4s)) //[]

	}

}
